package com.mall.project.sys.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mall.common.core.asserts.ApiAssert;
import com.mall.common.core.cons.AuthCons;
import com.mall.common.core.cons.StatusCons;
import com.mall.common.core.enums.ErrorCodeEnum;
import com.mall.common.redis.utils.RedisUtils;
import com.mall.common.security.utils.ApiUtils;
import com.mall.project.sys.mapper.UserMapper;
import com.mall.project.sys.model.dto.UserDTO;
import com.mall.project.sys.model.entity.User;
import com.mall.project.sys.model.parm.UserPARM;
import com.mall.project.sys.service.IUserService;
import org.apache.commons.codec.digest.Md5Crypt;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 系统用户表 服务实现类
 * </p>
 *
 * @author Sam
 * @since 2020-12-27
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private RedisUtils redisUtils;

    @Override
    public User currentUser() {
        return this.getById(ApiUtils.currentUid());
    }

    @Override
    public IPage<UserDTO> getPage(Page page, UserPARM userPARM) {
        return baseMapper.getPage(page, userPARM);
    }

    @Override
    public List<UserDTO> getList(UserPARM userPARM) {
        return baseMapper.getList(userPARM);
    }

    @Override
    public UserDTO getByIdEx(String id) {
        return baseMapper.getByIdEx(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createUser(UserPARM userPARM) {
        User user = userPARM.convert(User.class);
        String loginName = user.getLoginName();
        int count = this.count(Wrappers.<User>lambdaQuery().eq(User::getLoginName, loginName));
        ApiAssert.isFalse(ErrorCodeEnum.INTERNAL_SERVER_ERROR.convert("登录名重复，请更换登录名"), count > 0);
        //设置初始密码
        String password = pwdCrypt(StringUtils.isNotBlank(userPARM.getPassword()) ? userPARM.getPassword() : "888888");
        user.setPassword(password);
        ApiAssert.isTrue(ErrorCodeEnum.BAD_ADD_FAILURE, this.save(user));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delUser(String id) {
        ApiAssert.isFalse(ErrorCodeEnum.INTERNAL_SERVER_ERROR.convert("不允许操作管理员"), "1001".equals(id));
        //修改用户状态
        ApiAssert.isTrue(ErrorCodeEnum.BAD_DELETE_FAILURE, this.update(Wrappers.<User>lambdaUpdate()
                .set(User::getStatus, StatusCons.DISABLE).eq(User::getId, id)));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePwd(String password, String newPassword) {
        User user = this.currentUser();
        ApiAssert.isFalse(ErrorCodeEnum.INTERNAL_SERVER_ERROR.convert("不允许操作管理员"), "1001".equals(user.getId()));
        password = pwdCrypt(password);
        ApiAssert.isTrue(ErrorCodeEnum.INTERNAL_SERVER_ERROR.convert("原密码校验有误"), Objects.equals(password, user.getPassword()));
        newPassword = pwdCrypt(newPassword);
        doUpdatePwd(user.getId(), newPassword);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void resetPwd(String id, String password) {
        ApiAssert.isFalse(ErrorCodeEnum.INTERNAL_SERVER_ERROR.convert("不允许操作管理员"), "1001".equals(id));
        password = pwdCrypt(password);
        doUpdatePwd(id, password);
    }

    /**
     * 执行修改密码
     *
     * @param id
     * @param password
     */
    private void doUpdatePwd(String id, String password) {
        ApiAssert.isFalse(ErrorCodeEnum.INTERNAL_SERVER_ERROR.convert("不允许操作管理员"), "1001".equals(id));
        //执行修改
        User updateUser = new User();
        updateUser.setId(id);
        updateUser.setPassword(password);
        ApiAssert.isTrue(ErrorCodeEnum.INTERNAL_SERVER_ERROR.convert("修改失败"), this.updateById(updateUser));
    }

    /**
     * 密码加密
     *
     * @param password
     * @return
     */
    private String pwdCrypt(String password) {
        return Md5Crypt.apr1Crypt(password, AuthCons.PASSWORD_SALT);
    }
}
